package allod.som.input

import allod.som.Lattice.Pattern
import collection.mutable
import java.awt.image.BufferedImage
import allod.som.Metric
import java.awt.{Image}
import java.awt.color.ColorSpace

/**
 * Created by IntelliJ IDEA.
 * User: allod
 * Date: 7 квіт 2010
 * Time: 20:58:20
 */
class ImageInputSource(originalImage: Image,
                       colorSpace: ColorSpace,
                       metric: Metric,
                       splitWidth: Int,
                       splitHeight: Int) extends InputSource {
  val inputDimension = 3
  val elements = performImageComposition(originalImage)
  val labels = null

  def this(rgbImage: Image, colorSpace: ColorSpace, metric: Metric, splitSize: Int) =
    this (rgbImage, colorSpace, metric, splitSize, splitSize)

  private def performImageComposition(image: Image): Seq[Pattern] = {
    val segments = splitImage(image)
    val elementsBuffer = mutable.Set.empty[Pattern]
    segments.foreach(s => elementsBuffer ++= processSegment(s))
    elementsBuffer.toSeq
  }

  private def splitImage(image: Image): Seq[BufferedImage] = {
    val width = image.getWidth(null)
    val height = image.getHeight(null)

    val columns = 2 * width / splitWidth - 1
    val rows = 2 * height / splitHeight - 1

    for (i <- 0 until columns; j <- 0 until rows)
    yield {
      val srcStartX = i * splitWidth / 2
      val srcStartY = j * splitHeight / 2

      val srcEndX = srcStartX + splitWidth - 1
      val srcEndY = srcStartY + splitHeight - 1

      val img = new BufferedImage(splitWidth, splitHeight, BufferedImage.TYPE_INT_RGB)
      img.getGraphics.drawImage(image, 0, 0, splitWidth - 1, splitHeight - 1,
        srcStartX, srcStartY, srcEndX, srcEndY, null)
      img
    }
  }

  private def processSegment(segment: BufferedImage): Seq[Pattern] = {
    val width = segment.getWidth(null)
    val height = segment.getHeight(null)

    def getPixelData(index: Int) = {
      val rgb = segment.getRGB(index / width, index % width)
      val red: Int = (rgb >> 16) & 0xff;
      val green: Int = (rgb >> 8) & 0xff;
      val blue: Int = (rgb) & 0xff;
      val rgbArray = Array(red.toFloat, green.toFloat, blue.toFloat)
      colorSpace.fromRGB(rgbArray)
    }

    val pixelsCount = width * height

    val mid = new Array[Double](3)
    for (j <- 0 until pixelsCount) {
      val data = getPixelData(j)
      mid(0) = mid(0) + data(0)
      mid(1) = mid(1) + data(1)
      mid(2) = mid(2) + data(2)
    }
    val middle = List(mid(0) / pixelsCount, mid(1) / pixelsCount, mid(2) / pixelsCount)
    List(middle)
  }
}